#include "choosefrienddialog.h"

#include "model/data.h"
// #include "model/datacenter.h"
#include "publicmethods.h"
// #include "toast.h"
#include "debug.h"

#include <QHBoxLayout>
#include <QScrollArea>
#include <QScrollBar>
#include <QPushButton>
#include <QPainter>
#include <QMessageBox>
#include <QMouseEvent>

////////////////////////////////////////////////
/// 选择好友窗口中的一个 元素/好友项
////////////////////////////////////////////////

// 构造方法
ChooseFriendItem::ChooseFriendItem(ChooseFriendDialog *owner, const QString &userId, const QIcon &avatar, const QString &name, bool checked)
    : userId(userId)
{
    // 1. 设置控件的基本属性
    this->setFixedHeight(50); // 固定高度50px
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // 水平扩展，垂直固定

    // 2. 设置水平布局管理器
    QHBoxLayout* layout = new QHBoxLayout();
    layout->setSpacing(10); // 控件内元素间隔10px
    layout->setContentsMargins(20, 0, 20, 0); // 控件距离布局管理器左右边界各20px
    this->setLayout(layout);

    // 3. 创建复选框
    checkBox = new QCheckBox();
    checkBox->setChecked(checked); // 复选框的选中状态根据传入进来的checked确定
    checkBox->setFixedSize(25, 25); // 设置复选框固定尺寸
    QString style = "QCheckBox { background-color: transparent; } QCheckBox::indicator { width: 20px; height: 20px; image: url(:/resource/image/unchecked.png);}"; // 设置用图片代替展示选中、未选中状态的复选框
    style += "QCheckBox::indicator:checked { image: url(:/resource/image/checked.png);}";
    checkBox->setStyleSheet(style); // 设置复选框样式

    // 4. 创建头像
    avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(40, 40); // 头像尺寸
    avatarBtn->setIconSize(QSize(40, 40)); // 头像图片尺寸
    avatarBtn->setIcon(avatar); // 设置图片

    // 5. 创建名字
    nameLabel = new QLabel();
    nameLabel->setText(name); // 设置图片文字
    nameLabel->setStyleSheet("QLabel {background-color: transparent;}"); // 设置样式

    // 6. 添加 复选框、头像、名字 到布局管理器中
    layout->addWidget(checkBox);
    layout->addWidget(avatarBtn);
    layout->addWidget(nameLabel);

    // 7. 添加信号槽
    // 7.1. 复选框
    connect(checkBox, &QCheckBox::toggled, this, [=](bool checked) {
        if (checked)
        {
            // 勾选了复选框, 把当前这个 Item, 添加到右侧的已选择区域
            owner->addSelectedFriend(userId, avatar, name);
        } else
        {
            // 取消勾选
            owner->deleteSelectedFriend(userId);
        }
    });
}

void ChooseFriendItem::mousePressEvent(QMouseEvent *event)
{
    // 检查是否为鼠标左键点击
    if (event->button() == Qt::LeftButton)
    {
        // 切换复选框的选中状态
        if (checkBox)
        { // 确保 checkBox 是您界面中那个 QCheckBox 的成员变量指针
            checkBox->toggle(); // 切换状态
            // 注意：toggle() 会改变状态并发射 toggled 等信号，您之前连接的槽函数会自动触发
        }
        event->accept(); // 标记事件已处理
    }
    else
    {
        // 如果不是左键点击，传递给父类处理
        QWidget::mousePressEvent(event);
    }
}

// 绘制事件
void ChooseFriendItem::paintEvent(QPaintEvent *event)
{
    (void) event;

    // 根据鼠标的进入状态, 来决定绘制成不同的颜色
    QPainter painter(this);

    if (isHover)
    {
        // 绘制成深色
        painter.fillRect(this->rect(), QColor(230, 230, 230));
    }
    else
    {
        // 绘制成浅色
        painter.fillRect(this->rect(), QColor(255, 255, 255));
    }
}

// 鼠标进入事件
void ChooseFriendItem::enterEvent(QEnterEvent *event)
{
    (void) event;

    // 更新标志位
    isHover = true;

    // 更新界面
    this->update(); // 或者使用 this->repaint()
}

// 鼠标离开事件
void ChooseFriendItem::leaveEvent(QEvent *event)
{
    (void) event;

    isHover =  false;

    this->update();
}

////////////////////////////////////////////////
/// 选择好友的窗口
////////////////////////////////////////////////

// 构造方法
ChooseFriendDialog::ChooseFriendDialog(QWidget *parent, const QString &userId)
    : QDialog(parent)
    , userId(userId)
{
    // 1. 设置窗口的基本属性
    this->setWindowTitle("选择好友"); // 窗口标题
    this->setWindowIcon(QIcon(":/resource/image/logo.png")); // 窗口图标
    this->setFixedSize(750, 550); // 窗口固定尺寸
    this->setStyleSheet("QDialog { background-color: rgb(255, 255, 255);}"); // 窗体样式
    this->setAttribute(Qt::WA_DeleteOnClose); // 窗体关闭即释放资源

    // 2. 创建布局管理器
    QHBoxLayout* layout = new QHBoxLayout();
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    this->setLayout(layout);

    // 3. 针对左侧窗口进行初始化
    initLeft(layout);

    // 4. 针对右侧窗口进行初始化
    initRight(layout);

    // 5. 加载数据到窗口中
    initData();
}

// 初始化左侧保存左侧全部好友列
void ChooseFriendDialog::initLeft(QHBoxLayout *layout)
{
    // 1. 创建滚动区域
    QScrollArea* scrollArea = new QScrollArea(); // 创建滚动区对象
    scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 设置滚动区水平可伸展、垂直可伸展
    scrollArea->setWidgetResizable(true); // 设置滚动区尺寸可改变
    scrollArea->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0px;}"); // 设置水平滚动条样式
    scrollArea->verticalScrollBar()->setStyleSheet(PublicMethods::getVScrollBarStyle()); // 设置垂直滚动条样式
    scrollArea->setStyleSheet("QScrollArea { border:none; }"); // 设置滚动区样式
    layout->addWidget(scrollArea, 1); // 将滚动区加入父窗口的布局管理器，并设置伸缩因子

    // 2. 创建 QWidget 设置到滚动区域中.
    totalContainer = new QWidget(); // 创建滚动区的配套窗口
    totalContainer->setObjectName("totalContainer"); // 设置窗口名称
    totalContainer->setStyleSheet("#totalContainer { background-color: rgb(255, 255, 255); }"); // 根据名称设置样式
    scrollArea->setWidget(totalContainer); // 关联滚动区与窗口

    // 3. 创建 totalContainer 的 垂直布局管理器
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(0, 5, 0, 0);
    vlayout->setAlignment(Qt::AlignTop); // 元素靠上对齐
    totalContainer->setLayout(vlayout); // 将布局管理器添加到 totalContainer

    // 4. 创建 "提示" label 和 "全选" 按钮 的水平布局管理器
    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(20, 0, 20, 20);
    hlayout->setSpacing(10);
    vlayout->addLayout(hlayout);

    // 5. 创建 "提示" label
    QLabel* tipLabel = new QLabel();
    tipLabel->setText("你的好友列表");
    tipLabel->setFixedHeight(30);
    tipLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    tipLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    tipLabel->setStyleSheet("QLabel { font-size: 16px; font-weight: 700}");
    hlayout->addWidget(tipLabel);

    // 6. 创建 "全选" 按钮
    QPushButton *chooseAllBtn = new QPushButton();
    chooseAllBtn->setText("全选");
    chooseAllBtn->setFixedSize(QSize(56, 25));
    QString chooseAllBtnStyle = "QPushButton { background-color: rgb(7, 193, 96); border : none; border-radius : 8px; color: white; }";
    chooseAllBtnStyle += "QPushButton:hover { background-color: rgb(6, 183, 91); }";
    chooseAllBtnStyle += "QPushButton:pressed { background-color: rgb(6, 174, 86); }";
    chooseAllBtn->setStyleSheet(chooseAllBtnStyle);
    hlayout->addWidget(chooseAllBtn);

#if TEST_UI
    // 还需要进一步的添加 vlayout 内部的元素, 才能看到效果!
    // 此处也是先构造测试数据, 后续接入服务器之后, 从服务器拿到真实的好友列表, 再添加真实的数据
    QIcon defaultAvatar(":/resource/image/defaultAvatar.png");
    for (int i = 0; i < 30; ++i) {
        this->addFriend(QString::number(1000 + i), defaultAvatar, "张三" + QString::number(i), false);
    }
#endif

    connect(chooseAllBtn, &QPushButton::clicked, this, [=](){
        //
        // vlayout 遍历vlayout里的widget，
        // 判断widget是ChooseFriendItem
        // 如果是，再判断 checkBox 成员是否为空
        // 如果不为空就调用 checkBox->toggle(); // 切换状态
        //

        // 在开始批量操作前，禁用整个父控件的更新
        this->setUpdatesEnabled(false);

        for (int i = 0; i < vlayout->count(); ++i)
        {
            QLayoutItem *item = vlayout->itemAt(i);
            if (!item) continue;

            QWidget *widget = item->widget();
            ChooseFriendItem *friendItem = qobject_cast<ChooseFriendItem*>(widget);

            if (friendItem)
            {
                QCheckBox *itemCheckBox = friendItem->getCheckBox();

                if (itemCheckBox)
                {
                    // 1. 立即阻塞当前复选框的信号，防止toggle触发不必要的槽函数 [1,4](@ref)
                    itemCheckBox->blockSignals(true);

                    // 2. 判断当前复选框是否未选中
                    if (!itemCheckBox->isChecked())
                    {
                        // 3. 如果未选中，则切换状态至选中，并执行添加逻辑
                        itemCheckBox->toggle(); // 切换状态（选中）
                        addSelectedFriend(friendItem->getUserId(), friendItem->getAvatar(), friendItem->getName());
                    }
                    // 如果已经处于选中状态，则不做任何操作，避免重复添加

                    // 4. 立即恢复当前复选框的信号，使其能响应后续的用户交互 [1](@ref)
                    itemCheckBox->blockSignals(false);
                }
            }
        }

        // 操作完成后，恢复界面更新并强制刷新一次
        this->setUpdatesEnabled(true);
        this->update(); // 可选：确保界面立即刷新
    });
}

// 初始化右侧保存右侧选中好友列表
void ChooseFriendDialog::initRight(QHBoxLayout *layout)
{
    // 1. 创建右侧的（selectedContainer）布局管理器
    QGridLayout* gridLayout = new QGridLayout();
    gridLayout->setContentsMargins(20, 0, 20, 20);
    gridLayout->setSpacing(10);
    layout->addLayout(gridLayout, 1);

    // 2. 创建 "提示" label
    QLabel* tipLabel = new QLabel();
    tipLabel->setText("选择联系人");
    tipLabel->setFixedHeight(30);
    tipLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    tipLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    tipLabel->setStyleSheet("QLabel { font-size: 16px; font-weight: 700}");

    // 3. 创建滚动区域
    QScrollArea* scrollArea = new QScrollArea();
    scrollArea->setWidgetResizable(true);
    scrollArea->verticalScrollBar()->setStyleSheet(PublicMethods::getVScrollBarStyle());
    scrollArea->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal {height: 0px;}");
    scrollArea->setStyleSheet("QScrollArea {border: none;}");
    scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    // 4. 创建滚动区域中的 QWidget
    selectedContainer = new QWidget();
    selectedContainer->setObjectName("selectedContainer");
    selectedContainer->setStyleSheet("#selectedContainer { background-color: rgb(255, 255, 255); }");
    scrollArea->setWidget(selectedContainer);

    // 5. 创建 selectedContainer 中的 "垂直布局"
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(0, 0, 0, 0);
    vlayout->setAlignment(Qt::AlignTop);
    selectedContainer->setLayout(vlayout);

    // 6. 创建底部按钮
    QString style = "QPushButton { color: rgb(7, 191, 96); background-color: rgb(240, 240, 240); border: none; border-radius: 5px;}";
    style += "QPushButton:hover { background-color: rgb(220, 220, 220); } QPushButton:pressed { background-color: rgb(200, 200, 200); }";

    QPushButton* okBtn = new QPushButton();
    okBtn->setFixedHeight(40);
    okBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    okBtn->setText("完成");
    okBtn->setStyleSheet(style);

    QPushButton* cancelBtn = new QPushButton();
    cancelBtn->setFixedHeight(40);
    cancelBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    cancelBtn->setText("取消");
    cancelBtn->setStyleSheet(style);

    // 7. 把上述控件添加到布局中
    gridLayout->addWidget(tipLabel, 0, 0, 1, 9);
    gridLayout->addWidget(scrollArea, 1, 0, 1, 9);
    gridLayout->addWidget(okBtn, 2, 1, 1, 3);
    gridLayout->addWidget(cancelBtn, 2, 5, 1, 3);

#if TEST_UI
    // 构造一些数据用来进行测试界面
    // 此处的数据通过勾选左侧列表来生成.
    // QIcon defaultAvatar(":/resource/image/defaultAvatar.png");
    // for (int i = 0; i < 10; ++i) {
    //     this->addSelectedFriend(QString::number(1000 + i), defaultAvatar, "张三" + QString::number(i));
    // }
#endif

    // 8. 添加信号槽
    // 8.1 Ok点击
    connect(okBtn, &QPushButton::clicked, this, &ChooseFriendDialog::clickOkBtn);
    // 8.2 Canel点击
    connect(cancelBtn, &QPushButton::clicked, this, [=]() { this->close(); });
}

// 点击OK按钮
void ChooseFriendDialog::clickOkBtn()
{
#if TEST_UI
    QMessageBox::information(this, "提示", "群聊创建成功");
#endif
    // // 1. 根据选中的好友列表中的元素, 得到所有的要创建群聊会话的用户 id 列表
    // QList<QString> userIdList = generateMemberList();
    // if (userIdList.size() < 3) {
    //     Toast::showMessage("群聊中的成员不足三个, 无法创建群聊");
    //     return;
    // }

    // // 2. 发送网络请求, 创建群聊
    // DataCenter* dataCenter = DataCenter::getInstance();
    // dataCenter->createGroupChatSessionAsync(userIdList);

    // 3. 关闭当前窗口
    this->close();
}

//
QList<QString> ChooseFriendDialog::generateMemberList()
{
    QList<QString> result;

    // // 1. 把自己添加到结果中
    // DataCenter* dataCenter = DataCenter::getInstance();
    // if (dataCenter->getMyself() == nullptr) {
    //     LOG() << "个人信息尚未加载!";
    //     return result;
    // }
    // result.push_back(dataCenter->getMyself()->userId);

    // // 2. 遍历选中的列表
    // QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>(selectedContainer->layout());
    // for (int i = 0; i < layout->count(); ++i) {
    //     auto* item = layout->itemAt(i);
    //     if (item == nullptr || item->widget() == nullptr) {
    //         continue;
    //     }
    //     auto* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());
    //     result.push_back(chooseFriendItem->getUserId());
    // }

    return result;
}

// 初始化数据
void ChooseFriendDialog::initData()
{
    // // 遍历 好友列表, 把好友列表中的所有的元素, 添加到这个窗口界面上.
    // DataCenter* dataCenter = DataCenter::getInstance();
    // QList<UserInfo>* friendList = dataCenter->getFriendList();
    // if (friendList == nullptr) {
    //     LOG() << "加载数据时发现好友列表为空!";
    //     return;
    // }
    // for (auto it = friendList->begin(); it != friendList->end(); ++it) {
    //     if (it->userId == this->userId) {
    //         this->addSelectedFriend(it->userId, it->avatar, it->nickname);
    //         this->addFriend(it->userId, it->avatar, it->nickname, true);
    //     } else {
    //         this->addFriend(it->userId, it->avatar, it->nickname, false);
    //     }
    // }
}

// 添加好友
void ChooseFriendDialog::addFriend(const QString &userId, const QIcon &avatar, const QString &name, bool checked)
{
    ChooseFriendItem* item = new ChooseFriendItem(this, userId, avatar, name, checked);
    totalContainer->layout()->addWidget(item);
}

// 添加选中的好友
void ChooseFriendDialog::addSelectedFriend(const QString &userId, const QIcon &avatar, const QString &name)
{
    ChooseFriendItem* item = new ChooseFriendItem(this, userId, avatar, name, true);
    selectedContainer->layout()->addWidget(item);
}

// 删除选中的好友
void ChooseFriendDialog::deleteSelectedFriend(const QString &userId)
{
    //
    // 删除逻辑：
    // 1. 遍历 selectedContainer 中的每个 Item,
    // 2. 对比每个 Item 里的 userId
    // 3. 判断是否是要删除的 userId.
    //
    QVBoxLayout* vlayout = dynamic_cast<QVBoxLayout*>(selectedContainer->layout());

    // 由于是要 "遍历" + "删除" 需要从后往前进行
    for (int i = vlayout->count() - 1; i >= 0; --i)
    {
        auto* item = vlayout->itemAt(i);

        if (item == nullptr || item->widget() == nullptr)
        {
            continue;
        }

        ChooseFriendItem* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());

        // 判定当前的 Item 的 userId 是否是要删除的 userId
        if (chooseFriendItem->getUserId() != userId)
        {
            continue;
        }

        vlayout->removeWidget(chooseFriendItem);

        // 此处直接使用 delete 可能导致程序直接崩溃. 因为 delete 该对象的时候, 该对象内部的 QCheckBox 还在使用中 (触发着信号槽呢)
        // 改成 deleteLater, 就相当于把 delete 操作委托给 Qt 自身来完成了. 告诉 Qt 框架说, 你要删除这个对象. 至于啥时候删除 Qt
        // 会确保在 Qt 自身用完了之后, 去真正删除.
        // delete chooseFriendItem;
        chooseFriendItem->deleteLater();
    }

    // 再遍历一下左侧列表, 把左侧列表中对应 item 的 checkBox 勾选状态取消掉.
    QVBoxLayout* vlayoutLeft = dynamic_cast<QVBoxLayout*>(totalContainer->layout());

    for (int i = 0; i < vlayoutLeft->count(); ++i)
    {
        auto* item = vlayoutLeft->itemAt(i);

        if (item == nullptr || item->widget() == nullptr)
        {
            continue;
        }

        ChooseFriendItem* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());

        if (chooseFriendItem->getUserId() != userId)
        {
            continue;
        }

        // 取消 checkBox 选中状态
        chooseFriendItem->getCheckBox()->setChecked(false);
    }
}
